package com.demo.base.web.utils;

import com.demo.base.json.JSONObject;
import com.demo.base.web.webmvc.HttpContextConst;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by ethan on 2017/2/10.
 */
public abstract class RequestUtils {

    private static Logger logger = LoggerFactory.getLogger(RequestUtils.class);

    /**
     * 获取当前请求对象
     */
    public static HttpServletRequest getCurrentRequest() {
        return (HttpServletRequest) RequestContextHolder.currentRequestAttributes().getAttribute(HttpContextConst.CURRENT_HTTP_REQUEST, RequestAttributes.SCOPE_REQUEST);
    }

    /**
     * 获取当前输出对象
     */
    public static HttpServletResponse getCurrentResponse() {
        return (HttpServletResponse) RequestContextHolder.currentRequestAttributes().getAttribute(HttpContextConst.CURRENT_HTTP_RESPONSE, RequestAttributes.SCOPE_REQUEST);
    }

    /**
     * 根据cookie名字来获取一个cookie
     */
    public static Cookie getCookie(String name) {
        Cookie[] cookies = RequestUtils.getCurrentRequest().getCookies();
        if (cookies == null || cookies.length == 0) return null;

        Optional<Cookie> cookie = Arrays.stream(cookies)
                .filter(c -> c.getName().equals(name))
                .findFirst();
        return cookie.isPresent() ? cookie.get() : null;
    }

    public static String getCookieValue(String name) {
        Cookie cookie = getCookie(name);
        if (cookie != null) {
            return cookie.getValue();
        }
        return null;
    }

    public static String[] getCookieValues(String name) {
        String value = getCookieValue(name);
        if (StringUtils.hasText(value)) {
            return StringUtils.split(value, ",");
        }
        return null;
    }

    /**
     * 删除一个cookie
     *
     * @param name
     */
    public static void deleteCookie(String name) {
        Cookie cookie = getCookie(name);
        if (cookie == null) return;

        cookie.setPath("/");
        cookie.setMaxAge(0);
        RequestUtils.getCurrentResponse().addCookie(cookie);
    }

    public static void setCookie(Cookie cookie) {
        RequestUtils.getCurrentResponse().addCookie(cookie);
    }

    public static void setCookie(String name, String value) {
        setCookie(name, value, -1);
    }

    public static void setCookie(String name, String value, int expireSeconds) {
        setCookie(null, name, value, expireSeconds);
    }

    /**
     * 添加一个cookie
     *
     * @param expireSeconds 正数：有效时间；负数：随浏览器关闭而失效；0：删除
     */
    public static void setCookie(String domain, String name, String value, int expireSeconds) {
        Cookie cookie = getCookie(name);
        if (cookie == null) {
            cookie = new Cookie(name, value);
        }
        cookie.setPath("/");
        cookie.setMaxAge(expireSeconds);
        cookie.setDomain(domain);
        cookie.setSecure(true);
        cookie.setHttpOnly(true);
        RequestUtils.getCurrentResponse().addCookie(cookie);
    }

    /**
     * 获取所有请求参数
     */
    public static JSONObject getParameterMap() {
        JSONObject parameters = new JSONObject();
        for (Map.Entry<String, String[]> entry : getCurrentRequest().getParameterMap().entrySet()) {
            String[] values = entry.getValue();
            if (values.length == 0) {
                parameters.put(entry.getKey(), null);
            } else if (values.length == 1) {
                parameters.put(entry.getKey(), values[0]);
            } else {
                parameters.put(entry.getKey(), values);
            }
        }
        return parameters;
    }

    /**
     * 获取所有请求参数
     *
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static Map<String, String> getParamMap() {
        Map<String, String> parameters = new HashMap<String, String>();
        Map map = getCurrentRequest().getParameterMap();
        Set keys = map.keySet();
        for (Object key : keys) {
            parameters.put(key.toString(), getCurrentRequest().getParameter(key.toString()));
        }
        return parameters;
    }

    public static String[] getArray(String key) {
        return getCurrentRequest().getParameterValues(key);
    }

    public static String getString(String key) {
        return getString(key, null);
    }

    public static String getString(String key, String defaultValue) {
        String value = getCurrentRequest().getParameter(key);
        return StringUtils.hasText(value) ? value : defaultValue;
    }

    public static Integer getInteger(String key) {
        return getInteger(key, null);
    }

    public static Integer getInteger(String key, Integer defaultValue) {
        String value = getString(key);
        return (value == null) ? defaultValue : Integer.parseInt(value);
    }

    public static Long getLong(String key) {
        return getLong(key, null);
    }

    public static Long getLong(String key, Long defaultValue) {
        String value = getString(key);
        return (value == null) ? defaultValue : Long.parseLong(value);
    }

    public static BigInteger getBigInteger(String key) {
        return getBigInteger(key, null);
    }

    public static BigInteger getBigInteger(String key, BigInteger defaultValue) {
        String value = getString(key);
        return (value == null) ? defaultValue : new BigInteger(value);
    }

    public static BigDecimal getBigDecimal(String key) {
        return getBigDecimal(key, null);
    }

    public static BigDecimal getBigDecimal(String key, BigDecimal defaultValue) {
        String value = getString(key);
        return (value == null) ? defaultValue : new BigDecimal(value);
    }

    public static Date getDate(String key, String pattern) {
        return getDate(key, pattern, null);
    }

    public static Date getDate(String key, String pattern, Date defaultValue) {
        String value = getString(key);
        if (value == null)
            return defaultValue;
        try {
            return new SimpleDateFormat(pattern).parse(value);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public static boolean isOnlyAcceptJson() {
        String accept = getCurrentRequest().getHeader("Accept");
        if (StringUtils.isEmpty(accept)) return false;

        return accept.startsWith(MimeTypeUtils.APPLICATION_JSON_VALUE);
    }

    public String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if(ip.indexOf(",") > -1) {
            ip = ip.substring(0, ip.indexOf(","));
        }
        return ip;
    }
}
